home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Merciful 1
/
Merciful - Disc 1.iso
/
software
/
f
/
friday_night_pool
/
fridaynightpool.dms
/
fridaynightpool.adf
/
source
/
func.c
< prev
next >
Wrap
C/C++ Source or Header
|
1978-02-25
|
39KB
|
1,532 lines
#include <exec/types.h>
#include <exec/memory.h>
#include <graphics/view.h>
#include <intuition/intuition.h>
#include <graphics/gfxmacros.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <dos.h>
#include <proto/dos.h>
#include <math.h>
#include <exec/devices.h>
#include <devices/audio.h>
#include <hardware/custom.h>
#define CUE 0
#define BLK 5
#define BASE 200 /* V.important constant. Used in ALL physical calcs. */
#define BASESP 1000
#define BASEII 4 /* For root calcs which need plenty of precision */
#define TABLELENGTH (272 * BASE) /* 272 is actual length in pixels */
#define TABLEWIDTH ((TABLELENGTH * 5 / 8)-BASE)
#define X1CORNER 24
#define Y1CORNER 62
#define X2CORNER (X1CORNER + TABLELENGTH / BASE)
#define Y2CORNER (Y1CORNER + TABLEWIDTH / BASE)
#define BALLRADIUS (7 * BASE) /* 7 pixels */
#define BALLDIAMETER (BALLRADIUS * 2)
#define SCRNBALLDIAMETER (BALLDIAMETER / BASE)
#define SEMICIRCRAD (TABLEWIDTH/6)
#define PLACEPACK (TABLELENGTH * 5 / 8)
#define PACKHORIZSEP (BALLDIAMETER - 2*BASE)
#define POCKET (BALLRADIUS + 5*BASE)
#define SCRNPOCKET (POCKET / BASE)
#define CUETIP 10
#define MAXCUELENGTH 80
#define CLOCKWISE 1
#define ANTICLOCKWISE 2
#define SMALL 1
#define LARGE 2
#define UP 1
#define DOWN 2
#define NOHIT -1
#define ON TRUE
#define OFF FALSE
#define HIT 3
#define UPDATE 3
#define ICON 2
#define VIEW 1
#define NOREFRESH 2
#define RACKED 1
#define BROKEN 0
#define OPEN 2
#define SPREAD 3
#undef SINGLE
enum icons { PLYR1,PLYR2,PRACTICE,DEMO,PLAY,QUIT,_BAIZE,_BALL1,_BALL2,
SINGLE,BEST3,BEST5,UNLIMITED,STRIP,BALL10,BALL16,
OPPONENTBASE,ICON17,ICON18,ICON19,STRIPPERBASE };
enum args { GAMETYPE,GAMELENGTH,BAIZE,BALL1,BALL2,BALLCOUNT,OPPONENT,STRIPPER };
#define HUMANPLYR 0
#define COMPLYR 1
#define FRICTION (BASESP / 300)
#define SPINFRICTION 3
#define SPEEDINC (BASESP / 16)
#define MAXSPEED (BASESP * 4)
#define MINSPEED (BASESP / 4)
#define ESC 69
#define RETURN 68
#define SPACE 64
#define LCSR 79
#define RCSR 78
#define UCSR 76
#define DCSR 77
#define F1 80
#define F2 81
#define F3 82
#define F4 83
#define F6 85
#define F10 89
#define FLASH 2
#define JOYFIRE 0xbfe001
#define LMOUSE 1
#define RMOUSE 2
#define MEMSIZE 7000
void DoControl(void);
void DrawCue(short);
void ChangePower();
short ChangeSpin(void);
void DrawCross(short);
void MoveCue(short,short);
void DoAssigns(void);
void SetUpTable(void);
void DoOptions(void);
short GetInput(void);
char UpdateBallPos(void);
void WaitBeam(short);
short CheckPotted(short);
void CheckBounce(short);
void CheckCollision(void);
void MakeCollision(short,short);
void DrawBall(short,short);
void DrawBallDirect(short,short,short);
short FindAngle(WORD,WORD,WORD);
void SuperImpose(struct RastPort *,short,short,struct RastPort *,
short,short,short,short,short,short);
void WriteMessage(short,short,short,short);
void ScrubMessage(void);
void PlayShot(void);
void CheckResult(void);
void CheckWhitePotted(void);
short TouchingBall(short);
void PlayComputerShot(void);
void CopyBalls(struct ballstruct*,struct ballstruct*);
void CopyPlayer(short,short);
WORD QuickRoot(long);
short GetMouse(void);
char LoadIFF(struct IFFGraphic *,struct Screen *,char);
char ClickDelay(short);
void CueJumpAnim(void);
void CheckAngle(short *);
UWORD Rand(UWORD);
short AudioOpenIt(void);
long MyRead(struct FileHandle *,long *,long);
char OpenIt(void);
void CloseIt(void);
APTR GetDeviceBlock(ULONG);
void FreeDeviceBlock(struct IOAudio *,BYTE);
void Audio_PerVol(struct IOAudio *,UWORD,UWORD);
void Audio_Write(struct IOAudio *,UBYTE *,UWORD);
void PlaySound(struct audioinfostruct *,short);
/******************* Graphics defines ******************/
struct NewScreen ns;
struct NewWindow nw;
/* Extra padding for use with tempmask. Must set ballmask to point to */
/* first 'real' byte (8) at start of program */
USHORT chip crossmask[5];
USHORT chip mask[37];
USHORT chip mask2[10];
USHORT chip hybridmask[13];
USHORT chip hybridmask2[10];
USHORT chip miniball[8];
USHORT *ballmask = &mask[12];
USHORT *ballmask2 = mask2;
USHORT chip tempmask[256];
USHORT chip buffer[20];
/********************* System defines ************************/
struct Screen *s,*s2;
struct Window *w,*w2;
struct RastPort *rp,*rp2,bufrp;
struct BitMap *bm,*bm2,bufbm;
struct ViewPort *vp;
struct ColorMap *cm;
struct IntuiMessage *msg;
struct FileHandle *fh;
struct Preferences prefs;
UWORD *colorpalette;
char *bp0,*bp1,*bp2,*bp3,*bp4;
long oldkeyspeed,oldkeydelay;
/******************* Audio Defines ******************/
#define SAMPLES 8
#define AM2 106 /* Audio Master II info size */
#define BUFWAVELEN 100
enum sound { COLLIDE,STRIKE,BOUNCE,POTTED,CHEER,LONGCHEER,CHANT,CRASH };
#define AUDIO_LEN (sizeof(struct IOAudio))
#define PRECIDENCE 127
#define CLOSE_DEVICE 1
struct IOAudio *audio[4];
char Channel_Map[] = { 1,2,4,8 },*bufwave;
struct audioinfostruct
{
struct IOAudio *audio;
char *wave,bufstate,channel,flag;
long wavelen;
short volume,period;
char filename[30];
};
#define BUFFER 0
#define RESET 1
struct audioinfostruct audioinfo[SAMPLES];
/********************* Gameplay defines **********************/
UWORD rgb[32];
UWORD rgb2[32];
enum col {
_back,_leather,_dkleather,_ltbaize,_dkbaize,_dkwalnut,_walnut,_ltwalnut,
_baize,_yellow,_red,_ltbaize2,_white,_highyel,_highred,_ltbaize3,
_cross,_ptr17,_ptr18,_ptr19,_cuecol,_ltcuecol,_22,_23,
_black,_text1,_text2 };
enum balltype { white,black,yellow,red, anyball,baize };
char ballpalette[] = { _white,_black,_yellow,_red, 0,_baize };
char ball9colour[],ball15colour[];
char ballplanes[] = { 4,16,1,2, 0,23 };
struct ballstruct
{
enum balltype colour;
char potted,justpotted,hasmoved,lasthit,olddx,olddy;
USHORT x,y;
short speed,angle,scrnx,scrny,oldscrnx,oldscrny;
};
struct ballstruct ball[16],tempball[16];
struct playerstruct
{
enum balltype colour;
char goes,wins;
char nametag;
short maxpower;
char cuepulls,skill;
};
struct playerstruct player[8];
struct pixelsavestruct
{
char col;
short x,y;
};
struct pixelsavestruct pixelsave[32];
struct blitdatstruct
{
short x,y,dx,dy;
};
struct blitdatstruct blitdat,blitdat2;
short *memblock, *quicksin, *quickcos;
char *quickarcsin;
WORD cueangle=270,cuespeed=MINSPEED,powerdirn=UP,
spinx,spiny,swerve,swervetotal;
USHORT seed; /* random element */
short gametype,gamelength,stripper,opponent,
cueline,cloth,firsthit,turn,dotspacing=8,newbreak,cheer,
comp1,comp2,foul,endofgame,quitgame,winner,matches,coin,balls,
packstate,plyrbreak;
USHORT pocketx[6];
USHORT pockety[6];
char angleused[360];
char joydelay;
extern struct Custom far custom;
/********* Loader stuff *************/
extern struct IFFGraphic /* defined in load.c */
{
char FileName[30]; /* Name of IFF file */
BYTE ReqDepth; /* How many bitplanes wish to be Displayed */
USHORT *RGB; /* RGB colour values, filled by LoadIFF */
short Width; /* Width of graphic, filled by LoadIFF */
short Height; /* Height of graphic, filled by LoadIFF */
BYTE Depth; /* Depth of graphic, filled by LoadIFF */
};
extern char arg[8];
struct IFFGraphic tableIFF = { "fnpool:table.img",5,NULL };
UWORD RGBbaize[20];
UWORD RGBball[7];
UWORD RGBroom[16];
/********** Strip stuff *****************/
struct IFFGraphic roomIFF;
struct IFFGraphic stripIFF[4];
struct stripstruct
{ short imgx1[4],imgy1[4],imgdx[4],imgdy[4],imgx2[4],imgy2[4],
textfiletag[5],textx[5],texty[5],textdx[5],textdy[5]; };
/******* Message stuff *****************/
#define NEW 0
#define FOLLOW 1
short cursor;
enum msg { MSG_PLACECUEBALL,MSG_FOUL,MSG_WINS,MSG_MICHAEL,MSG_JOSH,
MSG_CLAIRE,MSG_SALLY,MSG_PLAYER1,MSG_PLAYER2,MSG_QUITTING,
MSG_VS,MSG_GAME,MSG_OF,MSG_0,MSG_1,MSG_2,MSG_3,MSG_4,MSG_5,
MSG_GOODSHOT,MSG_SHOTCANCELLED,MSG_BADLUCK,MSG_WELLDONE,
MSG_QUITGAME,MSG_ISTHECHAMP,MSG_OOOPS };
struct messagestruct { short x1,y1,x2,y2; };
struct messagestruct message[];
/************************/
char OpenIt()
{
short i;
if (!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0))) return(0);
if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",0))) return(0);
if (!(s2 = OpenScreen(&ns))) return(0);
if (!(s = OpenScreen(&ns))) return(0);
nw.Screen = s;
if (!(w = OpenWindow(&nw))) return(0);
nw.Screen = s2;
if (!(w2 = OpenWindow(&nw))) return(0);
if (!AudioOpenIt()) return(0);
if (!(memblock = AllocMem(MEMSIZE,MEMF_PUBLIC))) return(0);
cm = GetColorMap(32);
s->ViewPort.ColorMap = cm;
s2->ViewPort.ColorMap = GetColorMap(32);
rp = &s->RastPort; bm = &s->BitMap;
rp2 = &s2->RastPort; bm2 = &s2->BitMap;
colorpalette = (UWORD *)cm->ColorTable;
bp0 = s->BitMap.Planes[0]; bp1 = s->BitMap.Planes[1];
bp2 = s->BitMap.Planes[2]; bp3 = s->BitMap.Planes[3];
bp4 = s->BitMap.Planes[4];
for (i=0; i<32; i++) colorpalette[i] = 0;
MakeScreen(s); RethinkDisplay();
InitBitMap(&bufbm,5,320,256);
for (i=0; i<5; i++)
if (!(bufbm.Planes[i] = AllocRaster(320,256))) return(0);
InitRastPort(&bufrp); bufrp.BitMap = &bufbm;
bufrp.Mask = 31;
while (!(fh = (struct FileHandle *) Open("FNPGRAPHICS:message.img",MODE_OLDFILE)));
Seek((BPTR)fh,8,OFFSET_BEGINNING);
MyRead(fh,bufbm.Planes[0]+(175*40),(40*78));
MyRead(fh,bufbm.Planes[1]+(175*40),(40*78));
Close((BPTR)fh);
GetPrefs(&prefs,sizeof(struct Preferences));
prefs.KeyRptSpeed.tv_secs = 0;
oldkeyspeed = prefs.KeyRptSpeed.tv_micro;
prefs.KeyRptSpeed.tv_micro = 10000;
prefs.KeyRptDelay.tv_secs = 0;
prefs.KeyRptDelay.tv_micro = 300000;
oldkeydelay = prefs.KeyRptDelay.tv_micro;
prefs.PointerTicks = 1;
SetPrefs(&prefs,sizeof(struct Preferences),TRUE);
return(1);
}
/**********************/
void WriteMessage(i,x,y,flag)
short i,x,y,flag;
{
short dx = 1 + message[i].x2-message[i].x1;
short dy = 1 + message[i].y2-message[i].y1;
if (flag==NEW) { ScrubMessage(); cursor=5; }
SetWrMsk(rp,31); SetAPen(rp,_black);
RectFill(rp,x+cursor,7+y,x+cursor+dx,7+y+dy);
BltBitMap(&bufbm,message[i].x1,175 + message[i].y1,bm,x+cursor,7+y,
dx,dy,0xc0,3,buffer);
cursor += 10 + dx + x;
}
/***********************/
void ScrubMessage()
{
SetWrMsk(rp,31); SetAPen(rp,_black);
RectFill(rp,10,12,145,30);
}
/***********************/
void PlayShot()
{
short i,volume;
ball[CUE].angle = cueangle+180;
CheckAngle(&ball[CUE].angle);
ball[CUE].speed = cuespeed;
ball[CUE].lasthit = NOHIT;
firsthit=0; /* Which ball is hit first */
for (i=0; i<balls; i++) ball[i].justpotted=FALSE;
DrawCue(OFF); DrawCue(HIT);
if ((volume = 16 + (ball[CUE].speed<<6)/MAXSPEED) > 64) volume = 64;
PlaySound(&audioinfo[STRIKE],volume);
while(UpdateBallPos()) CheckCollision();
for (i=0; i<balls; i++) if (!ball[i].potted) DrawBall(i,ON);
spinx = 0; spiny = 0; swerve = 0; swervetotal = 0;
if (gametype==PRACTICE)
{
for (i=1; i<balls; i++) if (!ball[i].potted) break;
if (i==balls) /* No balls left on table */ endofgame=TRUE;
}
else
{
CheckResult();
if (player[turn].colour==black && !endofgame && cheer)
PlaySound(&audioinfo[CHANT],64);
}
if (packstate!=RACKED) newbreak=FALSE;
if (packstate==OPEN)
{
for (i=1; i<balls; i++) if (!ball[i].hasmoved) break;
if (i==balls) packstate=SPREAD;
}
cuespeed=MINSPEED;
if (endofgame) { DrawCue(ON); return; }
CheckWhitePotted();
WriteMessage(player[turn].nametag,5,5,NEW);
Delay(20); DrawCue(ON);
}
/**********************/
void CheckWhitePotted()
{
short returnhit=FALSE,angle,hyp;
if (ball[CUE].potted)
{
WriteMessage(MSG_PLACECUEBALL,5,5,NEW); Delay(50);
ball[CUE].potted = FALSE;
ball[CUE].x = (TABLELENGTH/4);
ball[CUE].y = (TABLEWIDTH/2 - BASE*3) + Rand(BASE*6);
ball[CUE].speed = 0;
while(TouchingBall(CUE)!=NOHIT)
{
/* White ball has been placed over another ball! */
angle = Rand(180);
hyp = Rand(SEMICIRCRAD);
ball[CUE].x = TABLELENGTH/4 -
quicksin[angle]*hyp/BASE;
ball[CUE].y = TABLEWIDTH/2 +
quickcos[angle]*hyp/BASE;
}
ball[CUE].scrnx = ball[CUE].x/BASE;
ball[CUE].scrny = ball[CUE].y/BASE;
DrawBall(CUE,ON);
if (!(gametype == DEMO || (gametype==PLYR1 && turn==COMPLYR)))
while(!returnhit)
{
short dx,dy,opp,adj;
dx=0; dy=0;
switch (GetInput())
{
case 76: dy=BASE; break;
case 77: dy=-BASE; break;
case 78: dx=BASE; break;
case 79: dx=-BASE; break;
case 68: returnhit = TRUE; break;
}
WaitTOF(); DrawBall(CUE,OFF);
opp = ((ball[CUE].x+=dx) - TABLELENGTH/4)/BASE;
adj = ((ball[CUE].y+=dy) - TABLEWIDTH/2)/BASE;
ball[CUE].scrnx = ball[CUE].x/BASE;
ball[CUE].scrny = ball[CUE].y/BASE;
if (opp > 0 ||
QuickRoot(opp*opp + adj*adj) > SEMICIRCRAD/BASE ||
TouchingBall(CUE)!=NOHIT)
{ ball[CUE].x-=dx; ball[CUE].y-=dy; }
DrawBall(CUE,ON);
}
ball[CUE].oldscrnx = ball[CUE].scrnx;
ball[CUE].oldscrny = ball[CUE].scrny;
}
}
/**********************/
void CopyPlayer(from,to)
short from,to;
{
player[to].nametag = player[from].nametag;
player[to].maxpower = player[from].maxpower;
player[to].cuepulls = player[from].cuepulls;
player[to].skill = player[from].skill;
player[to].wins = player[from].wins;
}
/**********************/
void SuperImpose(srcrp,x0,y0,destrp,x1,y1,dx,dy,transp,offset)
short x0,y0,dx,dy,x1,y1,transp,offset;
struct RastPort *srcrp,*destrp;
{
register short x,y,pixel;
for (y=0; y < dy; y++)
for (x=0; x < dx; x++)
if ((pixel = ReadPixel(srcrp,x0+x,y0+y)) != transp)
{ SetAPen(destrp,offset+pixel); WritePixel(destrp,x1+x,y1+y); }
}
/**********************/
short ChangeSpin()
{
short input,retnval=TRUE,new=FALSE,spinx2=spinx,spiny2=spiny;
rp->Mask = 31; DrawCross(ON);
do
{
input = GetInput();
switch(input)
{
case UCSR: if (spiny < 400) { spiny2=spiny+100; new=1; }
break;
case DCSR: if (spiny > -800) { spiny2=spiny-100; new=1; }
break;
case RCSR: if (spinx < 600) { spinx2=spinx+100; new=2; }
break;
case LCSR: if (spinx > -600) { spinx2=spinx-100; new=2; }
break;
case ESC: spinx2=0; spiny2=0; new=1; retnval=FALSE; break;
}
switch (new)
{
case 2:
{
short tempx = spinx,tempy = spiny;
DrawCue(OFF); spinx=spinx2; spiny=spiny2; DrawCue(ON);
spinx = tempx; spiny = tempy;
}
case 1:
DrawCross(OFF); spinx=spinx2; spiny=spiny2;
DrawCross(ON); new=FALSE; break;
}
} while (input!=RETURN && input!=ESC);
DrawCross(OFF);
swerve = abs(spiny) * spinx / 4800;
return retnval;
}
/**********************/
void DrawCross(status)
short status;
{
blitdat2.x = 157+spinx/100;
blitdat2.y = 14-spiny/100;
blitdat2.dx = 5; blitdat2.dy = 5;
if (status==OFF)
{
WaitBeam(40);
BltBitMap(&bufbm,0,85,bm,blitdat2.x,blitdat2.y,
blitdat2.dx,blitdat2.dy,0xc0,31,buffer);
}
else
{
SetAPen(rp,_cross);
BltBitMap(bm,blitdat2.x,blitdat2.y,&bufbm,
0,85,blitdat2.dx,blitdat2.dy,0xc0,31,buffer);
BltPattern(rp,crossmask,
157+spinx/100,14-spiny/100,
161+spinx/100,18-spiny/100,2);
}
}
/**********************/
void ChangePower()
{
short offset;
if (powerdirn==DOWN)
{
if ((cuespeed-=(SPEEDINC/2)) < MINSPEED)
{ powerdirn=UP; cuespeed=MINSPEED; }
}
else if ((cuespeed+=SPEEDINC) > MAXSPEED)
{ powerdirn=DOWN; cuespeed=MAXSPEED; }
offset = (cuespeed*16)/BASESP;
rp->Mask = 31;
WaitBeam(21);
SetAPen(rp,_back); RectFill(rp,201+offset,18,265,21);
SetAPen(rp,_white); RectFill(rp,199,18,200+offset,21);
}
/**********************/
void WaitBeam(y)
short y;
{
short vert;
while(1)
{
vert = VBeamPos();
if (vert > y+40 && vert < y+70) break;
}
}
/**********************/
void MoveCue(dirn,increment)
short dirn,increment;
{
DrawCue(OFF);
if (dirn==CLOCKWISE) cueangle += (increment==SMALL)? 1:10;
else cueangle -= (increment==SMALL)? 1:10;
CheckAngle(&cueangle);
DrawCue(ON);
}
/**********************/
void DoAssigns()
{
/* short i; */
quicksin = memblock;
quickcos = quicksin+361;
quickarcsin = quickcos+361;
/*
for (i=0; i<361; i++)
{
quicksin[i] = sin((double)i * PI / 180.0) * (double)BASE;
quickcos[i] = cos((double)i * PI / 180.0) * (double)BASE;
}
for (i=0; i<5001; i++)
quickarcsin[i] = asin((double)i / 5000.0) * 180.0 / PI;
*/
while (!(fh = (struct FileHandle *)Open("FNP:trig.dat",MODE_OLDFILE)));
Read((BPTR)fh,quicksin,361*2);
Read((BPTR)fh,quickcos,361*2);
Read((BPTR)fh,quickarcsin,5001);
Close((BPTR)fh);
}
/**********************/
short GetInput()
{
short code = NULL,code2;
ULONG joy = (ULONG)custom.joy1dat; /* joystick info */
if (joydelay==1) { Delay(10); joydelay=2; }
else if (!(gametype==PLYR2 && turn == 1))
{
if ((long)(joy & 768) == 512L) code = LCSR; /* Up-left */
else if ((long)(joy & 3) == 2L) code = RCSR; /* Down-right */
else if ((long)(joy & 3) == 3L) code = RCSR;
else if ((long)(joy & 768L) == 768L) code = LCSR;
else if ((long)(joy & 768) == 256L) code = UCSR;
else if ((long)(joy & 3) == 1L) code = DCSR;
else joydelay = 0;
if (!joydelay && code) joydelay=1;
while (!(*(char *)JOYFIRE & 0x80)) code = RETURN;
if (code==RETURN) Delay(20); /* Joystick fire */
}
if (!(msg = (struct IntuiMessage *)GetMsg(w->UserPort)))
return code;
do
{
code2 = msg->Code;
ReplyMsg((struct Message *)msg);
} while((msg = (struct IntuiMessage *)GetMsg(w->UserPort)) &&
code2!=ESC);
if (gametype==PLYR2 && turn == 0)
{
switch (code2)
{
case UCSR:
case DCSR:
case LCSR:
case RCSR:
case RETURN: return code;
}
}
return code2;
}
/**********************/
char UpdateBallPos()
{
short i,j,x1,y1,x2,y2,dx,dy;
char ballsmoving = FALSE;
for(i=0; i<balls; i++) /* Update ball position */
if (!ball[i].potted && ball[i].speed > 0)
{
ballsmoving=TRUE; ball[i].hasmoved=TRUE;
ball[i].x += ball[i].speed * quicksin[ball[i].angle] / BASESP;
ball[i].y += ball[i].speed * quickcos[ball[i].angle] / BASESP;
if ((ball[i].scrnx = ball[i].x/BASE) - ball[i].oldscrnx |
(ball[i].scrny = ball[i].y/BASE) - ball[i].oldscrny)
{
if (CheckPotted(i))
{ ball[i].potted = TRUE; ball[i].justpotted = TRUE; }
else CheckBounce(i);
if (ball[i].potted)
{
ball[i].scrnx = ball[i].oldscrnx;
ball[i].scrny = ball[i].oldscrny;
DrawBall(i,OFF);
}
else
{
USHORT *tmask = tempmask+(i<<4);
x1 = (X1CORNER-8) + ball[i].oldscrnx;
y1 = (Y2CORNER-7) - ball[i].oldscrny;
x2 = (X1CORNER-8) + ball[i].scrnx;
y2 = (Y2CORNER-7) - ball[i].scrny;
dx = x2-x1; dy = y2-y1;
if (dx != ball[i].olddx || dy != ball[i].olddy)
{
register USHORT *quickmask = ballmask;
if (dx >= 0) for (j=0; j<13; j++)
tmask[j] = quickmask[j] ^
(quickmask[j] & (*(quickmask+j-dy) >> dx));
else for (j=0; j<13; j++)
tmask[j] = quickmask[j] ^
(quickmask[j] & (*(quickmask+j-dy) << -dx));
ball[i].olddx = dx; ball[i].olddy = dy;
}
if (ball[i].colour != white)
{
register char *ptr = bp2 + (y1+3)*40 + ((x1+7)>>3);
register short data = 128 >> ((x1+7) % 8);
ptr[0] &= ~data; ptr[80] &= ~data;
if (data==1)
{ ptr[40] &= 252; ptr[41] &= 127; }
else if (data==128)
{ ptr[40] &= 63; ptr[39] &= 254; }
else ptr[40] &= ~(data + (data>>1) + (data<<1));
}
DrawBallDirect(ball[i].colour,x2,y2);
SetAPen(rp,_baize);
rp->Mask = ballplanes[ball[i].colour];
BltPattern(rp,tmask,x1,y1,x1+15,y1+12,2);
ball[i].oldscrnx = ball[i].scrnx;
ball[i].oldscrny = ball[i].scrny;
}
}
if (balls==10) ball[i].speed-=(FRICTION/2);
else ball[i].speed-=FRICTION;
if (ball[i].speed < 0) ball[i].speed = 0;
}
spinx -= (spinx > 0)? SPINFRICTION:-SPINFRICTION;
spiny -= (spiny > 0)? SPINFRICTION:-SPINFRICTION;
if ((swervetotal+=abs(swerve)) > 99)
{
ball[CUE].angle += (swerve > 0)? 1:-1;
CheckAngle(&ball[CUE].angle);
swervetotal-=100;
}
swerve -= (swerve > 0)? 1:-1;
return ballsmoving;
}
/**********************/
short CheckPotted(i)
short i;
{
BOOL potted = FALSE;
short volume;
register USHORT x = ball[i].x, y = ball[i].y;
if (ball[i].potted) return(FALSE);
if (x > (TABLELENGTH-BALLRADIUS) &&
(y < POCKET || y > (TABLEWIDTH-POCKET)))
potted = TRUE;
else if (x < BALLRADIUS && (y < POCKET || y > (TABLEWIDTH-POCKET)))
potted = TRUE;
else if (y < BALLRADIUS &&
(x < POCKET ||
(x > (TABLELENGTH/2 - POCKET/2) &&
x < (TABLELENGTH/2 + POCKET/2)) ||
x > (TABLELENGTH-POCKET)))
potted = TRUE;
else if (y > (TABLEWIDTH-BALLRADIUS) &&
(x < POCKET ||
(x > (TABLELENGTH/2 - POCKET/2) &&
x < (TABLELENGTH/2 + POCKET/2)) ||
x > (TABLELENGTH-POCKET)))
potted = TRUE;
if (potted)
{
if ((volume = 16 + (ball[i].speed<<6)/MAXSPEED) > 64) volume = 64;
PlaySound(&audioinfo[POTTED],volume);
if (ball[i].speed > (MAXSPEED*5/8) && !(Rand(4)))
{
ball[i].angle+=180; CheckAngle(&ball[i].angle);
ball[i].x += ball[i].speed * quicksin[ball[i].angle] / BASESP;
ball[i].y += ball[i].speed * quickcos[ball[i].angle] / BASESP;
ball[i].scrnx = ball[i].x/BASE; ball[i].scrny = ball[i].y/BASE;
ball[i].speed >>= 2; ball[i].lasthit=NOHIT; potted=FALSE;
}
}
return(potted);
}
/**********************/
void CheckBounce(i)
short i;
{
short bounce=FALSE,volume;
register USHORT x = ball[i].x, y = ball[i].y;
register short angle = ball[i].angle;
if (ball[i].potted) return;
if (x < BALLRADIUS && angle > 180)
{ angle=360-ball[i].angle; bounce=TRUE; }
else if (x > (TABLELENGTH-BALLRADIUS) && angle < 180)
{ angle=360-ball[i].angle; bounce=TRUE; }
else if (y < BALLRADIUS && angle < 270 && angle > 90)
{
if (angle <= 180) angle=180-ball[i].angle;
else angle=540-ball[i].angle; bounce=TRUE;
}
else if (y > (TABLEWIDTH-BALLRADIUS) && (angle > 270 || angle < 90))
{
if (angle <= 180) angle=180-ball[i].angle;
else angle=540-ball[i].angle; bounce=TRUE;
}
if (bounce)
{
if ((volume = 16 + (ball[i].speed<<6)/MAXSPEED) > 64) volume = 64;
PlaySound(&audioinfo[BOUNCE],volume);
if (ball[CUE].speed > (MAXSPEED*3/4) && spiny < -600 && !(Rand(3)))
CueJumpAnim();
ball[i].angle = angle;
ball[i].x += ball[i].speed * quicksin[ball[i].angle] / BASESP;
ball[i].y += ball[i].speed * quickcos[ball[i].angle] / BASESP;
ball[i].scrnx = ball[i].x/BASE; ball[i].scrny = ball[i].y/BASE;
if (ball[i].scrnx < (BALLRADIUS/BASE)) ball[i].scrnx = (BALLRADIUS/BASE);
else if (ball[i].scrnx > ((TABLELENGTH-BALLRADIUS)/BASE))
ball[i].scrnx = ((TABLELENGTH-BALLRADIUS)/BASE);
if (ball[i].scrny < (BALLRADIUS/BASE)) ball[i].scrny = (BALLRADIUS/BASE);
else if (ball[i].scrny > ((TABLEWIDTH-BALLRADIUS)/BASE))
ball[i].scrny = ((TABLEWIDTH-BALLRADIUS)/BASE);
ball[i].speed = ((ball[i].speed << 3) - ball[i].speed) >> 3;
ball[i].lasthit = NOHIT;
if (i==CUE)
{
ball[CUE].angle -= spinx / 25;
spinx = 0; spiny = 0; swerve = 0;
CheckAngle(&ball[CUE].angle);
}
if (packstate==BROKEN) packstate=OPEN; /* can now hear all collisions */
}
}
/**********************/
short GetMouse()
{
short status=0;
UBYTE *leftmouse = (UBYTE *)0xbfe001;
UWORD *rightmouse = (UWORD *)0xdff016;
if (!(*leftmouse & 0x40)) status |= LMOUSE;
if ((*rightmouse & 0x0400) != 0x0400) status |= RMOUSE;
return status;
}
/****************/
void SetUpTable()
{
short i,j,k,offset,oldoffset=0;
for (i=0; i<balls; i++) if (!ball[i].potted && ball[i].x)
{
ball[i].x = ball[i].oldscrnx*BASE;
ball[i].y = ball[i].oldscrny*BASE;
DrawBall(i,OFF);
}
ball[CUE].x = (TABLELENGTH/4);
ball[CUE].y = (TABLEWIDTH/2 - BASE*3) + Rand(BASE*6);
for (i=0,k=1; i<5; i++)
for (j=0; j<=i; j++,k++)
{
ball[k].x = (PLACEPACK-BASE) + PACKHORIZSEP*i;
ball[k].y = (TABLEWIDTH / 2) + (BALLDIAMETER *j) -
(BALLDIAMETER * i / 2) - BASE;
ball[k].x += Rand((BASE/2));
ball[k].y += Rand((BASE/2));
}
if (balls==10)
{
ball[7].y+=BALLDIAMETER; ball[8].y+=BALLDIAMETER;
ball[9].x+=PACKHORIZSEP; ball[9].y-=(BALLDIAMETER/2);
for (i=0; i<10; i++) ball[i].colour = ball9colour[i];
}
else for (i=0; i<16; i++) ball[i].colour = ball15colour[i];
BltBitMap(&bufbm,200,0,bm,182,107,71,79,0xc0,31,buffer);
if (gametype!=PRACTICE && cheer) PlaySound(&audioinfo[CHEER],64);
for (i=0; i<balls; i++)
{
ball[i].potted = FALSE; ball[i].speed = 0;
ball[i].lasthit = NOHIT;
ball[i].hasmoved = 0;
ball[i].scrnx = ball[i].x/BASE;
ball[i].scrny = ball[i].y/BASE;
ball[i].oldscrnx = ball[i].scrnx;
ball[i].oldscrny = ball[i].scrny;
ball[i].olddx = -99; ball[i].olddy = -99;
DrawBall(i,ON);
}
if (balls==16) for (j=0,k=25; j<5; j++,k-=5)
{
for (i=0; i<=360; i+=30)
{
offset = quicksin[i]*k/BASE;
WaitBeam(185);
BltBitMap(bm,(182-15)-oldoffset,107,
bm,(182-15)-offset,107,(71+30),79,0xc0,31,buffer);
if (i==90 || i==270) PlaySound(&audioinfo[COLLIDE],64);
oldoffset = offset;
}
}
Delay(30);
BltBitMap(bm,100,107,bm,182,107,71,79,0xc0,31,buffer);
for (i=1; i<balls; i++) DrawBall(i,ON);
if (coin==-1) coin = Rand(2);
coin = 1-coin; turn = coin;
if (balls==16)
{ player[0].colour = anyball; player[1].colour = anyball; }
else { player[0].colour = red; player[1].colour = red; }
player[turn].goes = 1;
if (gametype!=PRACTICE) DrawBall(player[turn].colour,ICON);
cueangle = 270; DrawCue(ON);
packstate=RACKED; plyrbreak=0; newbreak=TRUE;
}
/**********************/
void CheckBallDrag()
{
short i,x,y,button;
if (button = GetMouse())
{
x = s->MouseX; y = s->MouseY;
for (i=0; i<balls; i++)
{
if (!ball[i].potted &&
x > ball[i].scrnx+(X1CORNER-7) &&
x < ball[i].scrnx+(X1CORNER+8) &&
y > (Y2CORNER-8)-ball[i].scrny &&
y < (Y2CORNER+8)-ball[i].scrny &&
ReadPixel(rp,x,y) != _baize)
{
DrawCue(OFF);
if (button==RMOUSE && i!=CUE)
{
DrawBall(i,OFF);
ball[i].potted = TRUE;
PlaySound(&audioinfo[POTTED],64);
}
else if (button==LMOUSE)
{
PlaySound(&audioinfo[COLLIDE],64);
while (GetMouse() == LMOUSE)
{
short oldx,oldy;
x = s->MouseX; y = s->MouseY;
if (x < (X1CORNER+7)) x = (X1CORNER+7);
if (x > (X2CORNER-8)) x = (X2CORNER-8);
if (y < (Y1CORNER+8)) y = (Y1CORNER+8);
if (y > (Y2CORNER-7)) y = (Y2CORNER-7);
{
oldx = ball[i].x; oldy = ball[i].y;
ball[i].x = (x-X1CORNER)*BASE;
ball[i].y = (Y2CORNER-y)*BASE;
if (TouchingBall(i)==NOHIT)
{
WaitBeam(y+7); DrawBall(i,OFF);
ball[i].scrnx = ball[i].x/BASE;
ball[i].scrny = ball[i].y/BASE;
DrawBall(i,ON);
}
else { ball[i].x = oldx; ball[i].y = oldy; }
}
}
}
ball[i].oldscrnx = ball[i].scrnx;
ball[i].oldscrny = ball[i].scrny;
DrawCue(ON); while (GetMouse());
}
}
if (button==(LMOUSE|RMOUSE))
{
for (i=1; i<balls; i++)
if (ball[i].potted &&
x > (X1CORNER+6) && x < (X2CORNER-8) &&
y > (Y1CORNER+8) && y < (Y2CORNER-6))
{
ball[i].potted = FALSE;
ball[i].x = (x-X1CORNER)*BASE;
ball[i].y = (Y2CORNER-y)*BASE;
if (TouchingBall(i)==NOHIT)
{
DrawCue(OFF);
ball[i].scrnx = ball[i].x/BASE;
ball[i].scrny = ball[i].y/BASE;
ball[i].oldscrnx = ball[i].scrnx;
ball[i].oldscrny = ball[i].scrny;
ball[i].speed = 0;
WaitBeam(y+7); DrawBall(i,ON);
PlaySound(&audioinfo[COLLIDE],64);
DrawCue(ON); break;
}
else ball[i].potted = TRUE;
}
while (GetMouse());
}
}
}
/**********************/
void CheckCollision()
{
char i;
BOOL collision;
for(i=0; i<balls; i++) /* Check for collisions */
{
register short x1 = ball[i].scrnx + SCRNBALLDIAMETER;
register short y1 = ball[i].scrny + SCRNBALLDIAMETER;
register short x2 = x1 - (SCRNBALLDIAMETER*2);
register short y2 = y1 - (SCRNBALLDIAMETER*2);
register char j;
for(j=i+1; j<balls; j++)
{
/* Quick bounding box test to see if balls touch */
if (ball[j].scrnx < x1 && ball[j].scrnx > x2 &&
ball[j].scrny < y1 && ball[j].scrny > y2)
{
short dx = ball[j].x - ball[i].x;
short dy = ball[j].y - ball[i].y;
if (dx*dx + dy*dy < (BALLDIAMETER*BALLDIAMETER))
{
collision=TRUE;
/* Bug-fix to stop multiple collisions for same balls */
if (ball[j].lasthit==i && ball[i].lasthit==j)
collision=FALSE;
/* Balls are both stationary */
else if (!ball[i].speed && !ball[j].speed)
collision=FALSE;
/* Balls must be unpotted */
else if (ball[j].potted || ball[i].potted)
collision=FALSE;
if (collision) MakeCollision(i,j);
}
}
}
}
}
/**********************/
void DrawBallDirect(col,x,y)
short col,x,y;
{
SetAPen(rp,ballpalette[col]);
rp->Mask = ballplanes[col];
BltPattern(rp,ballmask,x,y,x+15,y+12,2);
if (col==baize) return;
if (col != white)
{
register char *ptr = bp2 + (y+3)*40 + ((x+7)>>3);
register short data = 128 >> ((x+7) % 8);
ptr[0] |= data; ptr[80] |= data;
if (data==1) { ptr[40] |= 3; ptr[41] |= 128; }
else if (data==128) { ptr[40] |= 192; ptr[39] |= 1; }
else ptr[40] |= data + (data>>1) + (data<<1);
}
}
/**********************/
void DrawBall(i,status)
short i,status;
{
short x = X1CORNER - 8 + ball[i].scrnx,
y = Y2CORNER - 7 - ball[i].scrny;
if (status==ON) DrawBallDirect(ball[i].colour,x,y);
else if (status==OFF) DrawBallDirect(baize,x,y);
else if (status==ICON)
{
DrawBallDirect(baize,287,11);
switch(i)
{
case red:
case yellow:
case black:
DrawBallDirect(i,287,11);
break;
case anyball:
DrawBallDirect(red,287,11);
ballmask = hybridmask; /* ballmask2 = hybridmask2; */
DrawBallDirect(baize,287,11);
DrawBallDirect(yellow,287,11);
ballmask = &mask[12]; /* ballmask2 = mask2; */ break;
}
}
}
/**********************/
void CheckResult()
{
short i,redpot=0,yellowpot=0,whitepot=0,blackpot=0,
redsleft=FALSE,yellowsleft=FALSE;
foul=FALSE;
for (i=0; i<balls; i++)
{
if (ball[i].justpotted) switch (ball[i].colour)
{
case red: redpot++; break;
case yellow: yellowpot++; break;
case black: blackpot++; break;
case white: whitepot++; break;
}
if (!ball[i].potted) switch (ball[i].colour)
{
case red: redsleft=TRUE; break;
case yellow: yellowsleft=TRUE; break;
}
}
switch(player[turn].colour)
{
case black:
if (blackpot)
{
endofgame=TRUE;
if (whitepot) foul=TRUE;
}
if (redpot || yellowpot) foul=TRUE;
if (ball[firsthit].colour!=black) foul=TRUE;
if (!blackpot) player[turn].goes=0;
break;
case red: /* Includes 9 ball variations... */
if (!redsleft)
{
player[turn].colour=black;
if (balls==10) player[1-turn].colour=black;
}
if (!yellowsleft && balls==16) player[1-turn].colour=black;
if (!redpot) player[turn].goes--;
if (blackpot)
{
endofgame=TRUE;
if (!newbreak) foul=TRUE;
break;
}
if (yellowpot) foul=TRUE;
if (ball[firsthit].colour!=red) foul=TRUE;
break;
case yellow:
if (!yellowsleft) player[turn].colour=black;
if (!redsleft) player[1-turn].colour=black;
if (!yellowpot) player[turn].goes--;
if (blackpot) { foul=TRUE; endofgame=TRUE; }
if (redpot) foul=TRUE;
if (ball[firsthit].colour!=yellow) foul=TRUE;
break;
case anyball:
if (blackpot)
{
endofgame=TRUE;
if (!newbreak) foul=TRUE;
break;
}
if (whitepot) foul=TRUE;
else if (ball[firsthit].colour != red &&
ball[firsthit].colour != yellow) foul=TRUE;
else if (yellowpot && !redpot)
{ player[turn].colour=yellow; player[1-turn].colour=red; }
else if (redpot && !yellowpot)
{ player[turn].colour=red; player[1-turn].colour=yellow; }
else if (!redpot && !yellowpot) player[turn].goes--;
break;
}
if (whitepot) foul=TRUE;
if (endofgame) winner = (foul)? winner = 1-turn:turn;
if (foul)
{
turn=1-turn; plyrbreak = 0;
if (player[turn].colour==black) player[turn].goes = 1;
else player[turn].goes = 2;
for (i=0; i<3; i++)
{
WriteMessage(MSG_FOUL,40,5,NEW); Delay(20);
ScrubMessage(); Delay(10);
if (GetInput() == RETURN) break;
}
}
else if (player[turn].goes==0)
{
if (plyrbreak > 2 && cheer) PlaySound(&audioinfo[CHEER],32);
turn=1-turn; plyrbreak = 0; player[turn].goes = 1;
}
else if ((redpot>1 || yellowpot>1 ||
(!ball[firsthit].potted && (redpot || yellowpot))) &&
!newbreak)
{
plyrbreak++; WriteMessage(MSG_GOODSHOT,5,5,NEW);
if (cheer) PlaySound(&audioinfo[CHEER],64); Delay(50);
}
else plyrbreak++;
if (gametype!=PRACTICE) DrawBall(player[turn].colour,ICON);
}
/**********************/
void DoOptions()
{
short i,j;
gametype = arg[GAMETYPE];
gamelength = arg[GAMELENGTH];
stripper = arg[STRIPPER];
opponent = arg[OPPONENT];
balls = arg[BALLCOUNT];
switch(gametype)
{
case PLYR1: CopyPlayer(2,0); CopyPlayer(opponent+4,1); break;
case PLYR2: CopyPlayer(2,0); CopyPlayer(3,1); break;
case PRACTICE: CopyPlayer(2,0); CopyPlayer(2,1); break;
case DEMO:
i = Rand(4); do j = Rand(4); while (i==j);
CopyPlayer(4+i,0); CopyPlayer(4+j,1); break;
}
if (gamelength==BEST3) matches=3;
else if (gamelength==BEST5) matches=5;
rgb2[_ltbaize] = RGBbaize[arg[BAIZE]*5];
rgb2[_dkbaize] = RGBbaize[arg[BAIZE]*5+1];
rgb2[_baize] = RGBbaize[arg[BAIZE]*5+2];
rgb2[_ltbaize2] = RGBbaize[arg[BAIZE]*5+3];
rgb2[_ltbaize3] = RGBbaize[arg[BAIZE]*5+4];
rgb2[_red] = RGBball[arg[BALL1]];
rgb2[_highred] = 0xfff;
rgb2[_yellow] = RGBball[arg[BALL2]];
rgb2[_highyel] = 0xfff;
FadeScreen(s,DOWN); SetRast(rp,_back);
for (i=0; i<32; i++) rgb[i] = rgb2[i];
if (gametype!=PRACTICE)
{
WriteMessage(player[0].nametag,80,80,NEW);
WriteMessage(MSG_VS,0,80,FOLLOW);
WriteMessage(player[1].nametag,0,80,FOLLOW);
FadeScreen(s,UP); ClickDelay(150);
}
LoadIFF(&tableIFF,s,VIEW);
BltBitMap(bm,182,107,&bufbm,200,0,71,79,0xc0,31,buffer);
}
/********************* Allocatation Routines ***********************/
short AudioOpenIt()
{
short i;
bufwave = AllocMem(BUFWAVELEN,MEMF_CLEAR | MEMF_CHIP);
for (i=0; i<4; i++)
{
if (!(audio[i] = (struct IOAudio *) GetDeviceBlock(AUDIO_LEN)))
return(0);
audio[i]->ioa_Data = &Channel_Map[i];
audio[i]->ioa_Length = 1; /* sizeof(Channel_Map); */
audio[i]->ioa_Request.io_Message.mn_Node.ln_Pri = PRECIDENCE;
if (OpenDevice("audio.device",NULL,audio[i],NULL)) return(0);
/* Cut out initial noise */
Audio_PerVol(audio[i],124,0);
Audio_Write(audio[i],bufwave,BUFWAVELEN);
}
for (i=0; i<SAMPLES; i++)
{
while (!(fh = (struct FileHandle *)
Open(audioinfo[i].filename,MODE_OLDFILE)));
audioinfo[i].audio = audio[audioinfo[i].channel];
audioinfo[i].wave =
AllocMem(audioinfo[i].wavelen,MEMF_CLEAR | MEMF_CHIP);
Seek((BPTR)fh,AM2,OFFSET_BEGINNING);
MyRead(fh,audioinfo[i].wave,audioinfo[i].wavelen);
Close((BPTR)fh);
}
return(1);
}
/************************/
void CloseIt()
{
short i;
prefs.KeyRptSpeed.tv_micro = oldkeyspeed;
prefs.KeyRptDelay.tv_micro = oldkeydelay;
SetPrefs(&prefs,sizeof(struct Preferences),TRUE);
for (i=0; i<4; i++)
FreeDeviceBlock(audio[i],(BYTE)CLOSE_DEVICE);
for (i=0; i<SAMPLES; i++) if (audioinfo[i].wave)
FreeMem(audioinfo[i].wave,audioinfo[i].wavelen);
if (bufwave) FreeMem(bufwave,BUFWAVELEN);
for (i=0; i<5; i++)
if (bufbm.Planes[i]) FreeRaster(bufbm.Planes[i],320,256);
if (memblock) FreeMem(memblock,MEMSIZE);
if (w) CloseWindow(w);
if (w2) CloseWindow(w2);
if (s) CloseScreen(s);
if (s2) CloseScreen(s2);
if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
if (GfxBase) CloseLibrary((struct Library *)GfxBase);
}
/**********************/
UWORD Rand(max)
UWORD max;
{
seed = seed*seed + 5*seed + VBeamPos();
return (seed % max);
}
/**********************/
void CheckAngle(angle)
short *angle;
{
if (*angle > 359) *angle-=360;
else if (*angle < 0) *angle+=360;
}
/**********************/
short FindAngle(opp,adj,hyp)
WORD opp,adj,hyp;
{
register short angle;
if (opp > hyp) opp=hyp;
else if (-opp > hyp) opp=-hyp;
angle = quickarcsin[abs(opp * 5000 / hyp)];
if (adj < 0 && opp >= 0) angle=180-angle;
else if (adj < 0 && opp < 0) angle+=180;
else if (adj >= 0 && opp < 0) angle=360-angle;
return angle;
}
/**********************/
WORD QuickRoot(x)
long x;
{
register USHORT y=2,dy;
register ULONG ysq;
while(y*y < x) y<<=1;
dy=y>>1;
while(1)
{
ysq = y*y;
if (ysq==x) return y;
if (ysq < x) y+=dy;
else y-=dy;
if (!(dy>>=1))
{
if (y*y < x) y++; /* add 1? - hyp not < opp or adj! */
return y;
}
}
}
/********************/
APTR GetDeviceBlock(size)
ULONG size;
{
struct MsgPort *port;
APTR request;
if (!(port = (struct MsgPort *) CreatePort(0,0))) return(NULL);
if (!(request = (APTR) CreateExtIO(port,size)))
{ DeletePort(port); return(NULL); }
return(request);
}
/********************/
void FreeDeviceBlock(audio,close)
struct IOAudio *audio;
BYTE close;
{
if (audio->ioa_Request.io_Message.mn_ReplyPort)
DeletePort(audio->ioa_Request.io_Message.mn_ReplyPort);
if (close && audio->ioa_Request.io_Device) CloseDevice(audio);
DeleteExtIO(audio);
}
/********************/
void PlaySound(info,volume)
struct audioinfostruct *info;
short volume;
{
if (CheckIO(info->audio))
{
info->volume = volume;
if (info->flag==RESET)
{
Audio_PerVol(info->audio,124,0);
Audio_Write(info->audio,info->wave,info->wavelen);
while(!(CheckIO(info->audio)));
Audio_PerVol(info->audio,info->period,info->volume);
Audio_Write(info->audio,bufwave,BUFWAVELEN);
}
else /* flag == BUFFER */
{
Audio_PerVol(info->audio,info->period,info->volume);
if (info->bufstate = 1 - info->bufstate)
Audio_Write(info->audio,info->wave,info->wavelen);
else Audio_Write(info->audio,bufwave,BUFWAVELEN);
}
}
}
/********************/
void Audio_PerVol(audio,period,volume)
struct IOAudio *audio;
UWORD period,volume;
{
audio->ioa_Request.io_Flags = ADIOF_SYNCCYCLE;
audio->ioa_Period = period;
audio->ioa_Volume = volume;
audio->ioa_Request.io_Command = ADCMD_PERVOL;
SendIO(audio);
}
/********************/
void Audio_Write(audio,waveform,wavelength)
struct IOAudio *audio;
UBYTE *waveform;
UWORD wavelength;
{
audio->ioa_Data = waveform;
audio->ioa_Request.io_Command = CMD_WRITE;
audio->ioa_Request.io_Flags = 0;
audio->ioa_Length = wavelength;
audio->ioa_Cycles = 1;
SendIO(audio);
}
/************************/
void CopyBalls(fromball,toball)
struct ballstruct *fromball,*toball;
{
short i;
for (i=0; i<balls; i++)
{
toball[i].x = fromball[i].x;
toball[i].y = fromball[i].y;
toball[i].scrnx = fromball[i].scrnx;
toball[i].scrny = fromball[i].scrny;
toball[i].angle = fromball[i].angle;
toball[i].speed = fromball[i].speed;
toball[i].potted = fromball[i].potted;
toball[i].justpotted = fromball[i].justpotted;
}
}